package pl.edu.agh.iosr.gamblingzone.userpanel.action;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.util.Calendar;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import javax.ejb.Remove;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.Create;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.annotations.security.Restrict;
import org.jboss.seam.faces.FacesMessages;
import org.richfaces.event.DropEvent;

import pl.edu.agh.iosr.gamblingzone.dao.AbstractEventDAO;
import pl.edu.agh.iosr.gamblingzone.dao.BetDAO;
import pl.edu.agh.iosr.gamblingzone.dao.BettingSlipDAO;
import pl.edu.agh.iosr.gamblingzone.dao.ParticipantDAO;
import pl.edu.agh.iosr.gamblingzone.dao.UserDAO;
import pl.edu.agh.iosr.gamblingzone.model.AbstractEvent;
import pl.edu.agh.iosr.gamblingzone.model.Bet;
import pl.edu.agh.iosr.gamblingzone.model.BettingSlip;
import pl.edu.agh.iosr.gamblingzone.model.Participant;
import pl.edu.agh.iosr.gamblingzone.model.User;
import pl.edu.agh.iosr.gamblingzone.utils.DAOFactory;

@Stateful
@Scope(ScopeType.SESSION)
@Name("tempSlip")
@Restrict("#{identity.loggedIn}")
public class TempBettingSlipViewAction implements TempBettingSlipView {
	
	final public static Double INCOME_RATE = 0.1;
	
	@In
	private User user;
	
	@In(required=true)
	DAOFactory dao;
	
	@In
	private FacesMessages facesMessages;

	@PersistenceContext
	private EntityManager em;
	
	private List<Bet> bets = new LinkedList<Bet>();
	
	private String stake = "0.00";
	
	private String winning = "0.00";
	
	private DecimalFormat formatter;

	@Remove
	public void destroy() {

	}

	@Create
	public void init() {
		BetDAO betDAO = dao.getBetDAO();
		bets = betDAO.findAll(user.getTempBettingSlip(), 0);
		
		formatter = new DecimalFormat("#0.00#");
	}

	public void acceptTempSlip() {
		facesMessages.add("Specify amount of money");
		facesMessages.add("Specify amount of money");
		facesMessages.add("Specify amount of money");
		
		Double money = null;
		
		// validate data 
		try {
			Number tmpMoney = formatter.parse(winning);
			money = tmpMoney.doubleValue();
			
			if (money == null || money <= 0.0) {
				facesMessages.add("Specify amount of money");
				return;
			}
			
		} catch (ParseException e) {
			e.printStackTrace();
		}
		
		if (money == null) {
			return;
		}
		
		BettingSlipDAO slipDAO = dao.getSlipDAO();
		UserDAO userDAO = dao.getUserDAO();
		
		BettingSlip oldTempSlip = user.getTempBettingSlip();
		
		// add new tempSlip
		BettingSlip newTempSlip = new BettingSlip();
		newTempSlip = slipDAO.makePersistent(newTempSlip);
		user.setTempBettingSlip(newTempSlip);
		
		// add old to slips
		user = userDAO.makePersistent(user);
		oldTempSlip = slipDAO.makePersistent(oldTempSlip);
		user.addBettingSlip(oldTempSlip);
		
		init();
	}

	public void removeBet(Bet b) {
		BetDAO betDAO = dao.getBetDAO();
		betDAO.makeTransient(b);
		
		init();
		setStake(stake);
	}

	public String betDescription(Bet b) {
		String outParticipants = "";

		for (AbstractEvent ae: b.getEvents()) {
			if (ae.getRates().size() > 2) {
				outParticipants += "Kto wygra "+ae.getGroup().getName();
			} else {
				for (Participant p : ae.getRates().keySet()) {
					outParticipants += p.getName()+" - ";
				}
				outParticipants = outParticipants.substring(0, outParticipants.length()-3);
			}
		}
		
		return outParticipants;
	}

	public String getRate(Bet b) {

        Participant winner = b.getWinner();
        Double rate = 0.0;

        for (AbstractEvent ae: b.getEvents()) {
            rate = ae.getRates().get(winner);
        }
        
        if (rate != null && rate != 0.0) {
            rate = 1.0 / (rate + INCOME_RATE);
        }
        if (rate < 1.0) rate = 1.0;
        
        return String.format("%.2f", rate);
    }
	public String getStake() {
		return stake;
	}
	
	private double getGlobalRate() {
		Double ret = 1.0;
		
		for (Bet b : bets) {
			Double tmpRet = 0.0;
			
			for (AbstractEvent ae: b.getEvents()) {
				tmpRet = ae.getRates().get(b.getWinner());
			}
			
			System.out.println("====== "+tmpRet);
			if (tmpRet != null && tmpRet != 0.0) {
				tmpRet = 1.0/tmpRet+INCOME_RATE;
			}
			
			ret *= tmpRet;
		}
		
		return ret;
	}

	public void setStake(String stake) {
		Double tmpStake = null;
		try {
			Number in = formatter.parse(stake);
			tmpStake = in.doubleValue();
			this.stake = stake;
			this.winning = formatter.format(tmpStake*getGlobalRate());
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	public String getWinning() {
		return winning;
	}

	public void setWinning(String winning) {
		Double tmpWinning = null;
		try {
			Number in = formatter.parse(winning);
			tmpWinning = in.doubleValue();
			this.winning = winning;
			this.stake = formatter.format(tmpWinning/getGlobalRate());
		} catch (ParseException e) {
			e.printStackTrace();
		}
	}

	public List<Bet> getBets() {
		return bets;
	}

	public void setBets(List<Bet> bets) {
		this.bets = bets;
	}

	public List<Bet> retrieveBets() {
		init();
		
		return bets;
	}

	public String getTotalOdds() {
		return String.format("%.2f", getGlobalRate());
	}
	
	public void addBet(DropEvent event) {
	
		Object value  = event.getDropValue();
		
		Bet retrievedBet = (Bet)value;
		
		if (retrievedBet == null) {
			System.out.println("=============================================================================");
		}
		
		ParticipantDAO participantDAO = dao.getParticipantDAO();
		BettingSlipDAO betSlipDAO = dao.getSlipDAO();
		AbstractEventDAO abEventDAO = dao.getEventDAO();
		
		Bet newBet = new Bet();
		Participant winner = retrievedBet.getWinner();
		if (winner == null) {
			return;
		}
		// add events
		Set<AbstractEvent> evetsList = retrievedBet.getEvents();
		int i = 0;
		for (AbstractEvent ae: evetsList) {
			if (i < 1) {
				AbstractEvent tmpEvent = new AbstractEvent();
				for (Participant par: ae.getRates().keySet()) {
						par = participantDAO.makePersistent(par);
						tmpEvent.getRates().put(par, ae.getRates().get(par));
				}
				Calendar calendar = Calendar.getInstance();
				calendar.add(Calendar.DAY_OF_WEEK, 1);
				tmpEvent.setClosingDate(calendar.getTime());
				tmpEvent = abEventDAO.makePersistent(tmpEvent);
				newBet.addEvent(tmpEvent);
			}
			i++;
		}
		winner = participantDAO.makePersistent(winner);
		newBet.setWinner(winner);
		BettingSlip tempBettingSlip = user.getTempBettingSlip();
		tempBettingSlip = betSlipDAO.makePersistent(tempBettingSlip);
		tempBettingSlip.addBet(newBet);
		
		em.flush();
		
		init();
		
		System.out.println("=============================================================================");
		System.out.println("=============================================================================");
		System.out.println("=============================================================================");
		System.out.println("=============================================================================");
	}
}
